package com.koron.order.defect.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.koron.bean.system.staff.po.AppUserPo;
import com.koron.common.core.util.StringUtils;
import com.koron.common.core.util.message.MessageUtil;
import com.koron.order.change.dispatch.mapper.ChangeDispatchMapper;
import com.koron.order.change.util.ThreadLocalOrderChange;
import com.koron.order.common.bean.base.OrderType;
import com.koron.order.common.bean.dto.OrderDispatchDto;
import com.koron.order.common.bean.po.OrderDispatch;
import com.koron.order.common.bean.po.OrderLocationPo;
import com.koron.order.common.bean.po.OrderReassignPo;
import com.koron.order.common.service.*;
import com.koron.order.defect.bean.convertor.DefectConvertor;
import com.koron.order.defect.bean.dto.DefectDTO;
import com.koron.order.defect.bean.po.DefectBean;
import com.koron.order.defect.bean.po.DefectDispatch;
import com.koron.order.defect.bean.po.DefectStatus;
import com.koron.order.defect.bean.vo.DispatchVO;
import com.koron.order.defect.mapper.DispatchMapper;
import com.koron.order.defect.service.DefectDispatchService;
import com.koron.order.defect.service.DefectService;
import com.koron.order.defect.service.DispatchService;
import com.koron.order.maintain.bean.entity.MaintainPo;
import com.koron.order.maintain.service.MaintainService;
import com.koron.order.overhaul.bean.entity.OverhaulOrderBean;
import com.koron.order.overhaul.service.OverhaulOrderService;
import com.koron.order.repair.bean.entity.RepairPo;
import com.koron.order.repair.service.RepairService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName DispatchServiceImpl
 * @description
 * @Author zhouj
 * @Date 2021/9/3 17:50
 */
@Slf4j
@Service
public class DispatchServiceImpl implements DispatchService {

    @Autowired
    DefectDispatchService defectDispatchService;

    @Autowired
    OrderDispatchInfoService orderDispatchInfoService;

    @Autowired
    OrderDispatchService orderDispatchService;

    @Autowired
    OrderDispatchWorkerService orderDispatchWorkerService;

    @Autowired
    DefectService defectService;

    @Autowired
    DefectConvertor defectConvertor;

    /*工单的工作地点*/
    @Autowired
    OrderWorkDeptService orderWorkDeptService;

    @Autowired
    OrderReassignService orderReassignService;

    /*工单的工作地点*/
    @Autowired
    OrderLocationService orderLocationService;

    @Autowired
    MessageUtil messageUtil;


    public static final Map<String, Object> ORDER_SERVICE = new HashMap<>();
    public static final Map<String, Class<?>> ORDER_TYPE = new HashMap<>();

    static {
        ORDER_TYPE.put(OrderType.DEFECT, DefectBean.class);
        ORDER_TYPE.put(OrderType.MAINTAIN, MaintainPo.class);
        ORDER_TYPE.put(OrderType.OVERHAUL, OverhaulOrderBean.class);
        ORDER_TYPE.put(OrderType.REPAIR, RepairPo.class);
    }

    @PostConstruct
    public void init() {
        ORDER_SERVICE.put(OrderType.DEFECT, SpringUtil.getBean(DefectService.class));
        ORDER_SERVICE.put(OrderType.MAINTAIN, SpringUtil.getBean(MaintainService.class));
        ORDER_SERVICE.put(OrderType.OVERHAUL, SpringUtil.getBean(OverhaulOrderService.class));
        ORDER_SERVICE.put(OrderType.REPAIR, SpringUtil.getBean(RepairService.class));
    }

    //查询单个派单详情
    @Override
    @TaskAnnotation("querySingle")
    public DispatchVO querySingle(SessionFactory factory, DispatchVO dispatchVO) {

        DispatchMapper mapper = getDispatchMapper(factory);
        DispatchVO dispatchVO1 = mapper.querySingle(dispatchVO);

        return dispatchVO1;
    }

    //保存三个表单派工信息的信息
    @Override
    @TaskAnnotation("saveDispatch")
    public String saveDispatch(SessionFactory factory, DispatchVO dispatchVO) {

        //vo转工单派工bean
        OrderDispatchDto orderDispatchDto = defectConvertor.voToOrderDispatchDto(dispatchVO);
        String orderId = dispatchVO.getOrderId();

        //1.1 派工信息表
        String dispatchId = orderDispatchInfoService.insertOrUpdate(factory, orderDispatchDto);

        //1.2 工作地点关联表
        List<OrderLocationPo> orderLocationList = dispatchVO.getOrderLocationList();
        //不为空则赋值
        if (CollectionUtils.isNotEmpty(orderLocationList)) {
            orderLocationList.forEach(p -> {
                p.setOrderId(dispatchVO.getOrderId());
                p.setOrderType(OrderType.DEFECT);
            });
            orderLocationService.insertBatch(factory, orderLocationList);
        } else {
            orderLocationService.deleteByOrderId(factory, orderId);
        }

        //vo转缺陷派工bean
        DefectDispatch defectDispatch = defectConvertor.voToDefectDispatchBean(dispatchVO);
        defectDispatch.setDefectId(orderDispatchDto.getOrderId());

        //1.3 缺陷派工表
        defectDispatchService.insertOrUpdate(factory, defectDispatch);

        if (dispatchVO.getIsCommit()) {
            //修改工单状态 待派工-->待执行
            defectService.submitDefect(factory, dispatchVO.getOrderId(), DefectStatus.WAIT_EXECUTE.getStatus());

            //修改转派工单的派工状态
            OrderReassignPo orderReassignPo = new OrderReassignPo();
            orderReassignPo.setOrderId(dispatchVO.getOrderId());
            orderReassignPo.setDispatch(true);
            orderReassignPo.setWorker(getCurrUser().getAccount());
            orderReassignService.updateByOrderId(factory, orderReassignPo);

            // 缺陷工单发送派工通知
            if (StringUtils.isNotEmpty(orderDispatchDto.getTopicWorker())) {
                String topicWorkerJson = orderDispatchDto.getTopicWorker();
                List<AppUserPo> userPoList = JSONUtil.parseArray(topicWorkerJson).toList(AppUserPo.class);
                String handler = userPoList.stream().map(AppUserPo::getAccount).collect(Collectors.joining(","));
                sendMessage(handler, orderDispatchDto);
            }
        }

        return dispatchId;

    }

    private void sendMessage(String handler, OrderDispatch orderDispatch) {
        String qywxHref = messageUtil.generateQywxHref("transmit_" + orderDispatch.getOrderType() + "_order", orderDispatch.getOrderId(), "", "");
        messageUtil.sendMessageWithTemplate("dispatch_notice", qywxHref, handler, orderDispatch.getContext());
    }

    @Override
    @TaskAnnotation("deleteByOrderId")
    public int deleteByOrderId(SessionFactory factory, String orderId) {

        orderDispatchService.deleteByOrderId(factory, orderId);
        orderDispatchWorkerService.deleteByOrderId(factory, orderId);
        defectDispatchService.deleteByOrderId(factory, orderId);
        orderWorkDeptService.deleteByOrderId(factory, orderId);

        return 1;
    }


    //转派工单
    @Override
    @TaskAnnotation("reassign")
    public OrderReassignPo reassign(SessionFactory factory, OrderReassignPo orderReassignPo) {

        orderReassignPo.setOrderType(orderReassignPo.getOrderType());
        orderReassignService.insertOrUpdate(factory, orderReassignPo);

        //工单修改为待派工状态
        try {
            process(factory, orderReassignPo.getOrderType(), orderReassignPo);
        } catch (Exception e) {
            log.error("转派工单失败："+e.getMessage()+",错误信息：" + Arrays.toString(e.getStackTrace()));
        }

        return orderReassignPo;
    }

    public void process(SessionFactory factory, String orderType, OrderReassignPo orderReassignPo) throws Exception {

        Class<?> aClass = ORDER_TYPE.get(orderType);
        if (aClass == null){
            throw new RuntimeException("不支持当前工单类型："+orderType);
        }
        Object order = aClass.getDeclaredConstructor().newInstance();
        Field fieldId = null;
        Field fieldMajor = null;
        Field fieldStatus = null;
        Field fieldUpdateBy = null;
        Field fieldUpdateByName = null;
        Field fieldUpdateTime = null;
        try {
            fieldId = aClass.getSuperclass().getDeclaredField("id");
            fieldMajor = aClass.getDeclaredField("major");
            fieldStatus = aClass.getDeclaredField("status");
            fieldUpdateBy = aClass.getSuperclass().getDeclaredField("updateBy");
            fieldUpdateByName = aClass.getSuperclass().getDeclaredField("updateByName");
            fieldUpdateTime = aClass.getSuperclass().getDeclaredField("updateTime");
        } catch (Exception e) {
            fieldId = aClass.getDeclaredField("id");
            fieldMajor = aClass.getDeclaredField("major");
            fieldStatus = aClass.getDeclaredField("status");
            fieldUpdateBy = aClass.getDeclaredField("updateBy");
            fieldUpdateByName = aClass.getDeclaredField("updateByName");
            fieldUpdateTime = aClass.getDeclaredField("updateTime");
        }

        fieldId.setAccessible(true);
        fieldMajor.setAccessible(true);
        fieldStatus.setAccessible(true);
        fieldUpdateBy.setAccessible(true);
        fieldUpdateByName.setAccessible(true);
        fieldUpdateTime.setAccessible(true);

        fieldId.set(order, orderReassignPo.getOrderId());
        fieldMajor.set(order, orderReassignPo.getMajor());
        fieldStatus.set(order, DefectStatus.WAIT_DISPATCH.getStatus());
        fieldUpdateBy.set(order, orderReassignPo.getWorker());
        fieldUpdateByName.set(order, orderReassignPo.getWorkerName());
        fieldUpdateTime.set(order, new Date());

        log.info("转派工单基本信息为："+JSONUtil.toJsonStr(order));

        switch (orderType){
            case "defect":
                DefectService defectService = (DefectService) ORDER_SERVICE.get(orderType);
                DefectBean defectBean = (DefectBean) order;
                DefectDTO defectDTO = new DefectDTO();
                BeanUtil.copyProperties(defectBean, defectDTO);
                defectService.update(factory, defectDTO);
                return;
            case "maintain":
                MaintainService maintainService = (MaintainService) ORDER_SERVICE.get(orderType);
                maintainService.update(factory, (MaintainPo) order);
                return;
            case "overhaul":
                OverhaulOrderService overhaulOrderService = (OverhaulOrderService) ORDER_SERVICE.get(orderType);
                overhaulOrderService.update(factory, (OverhaulOrderBean) order);
                return;
            case "repair":
                RepairService repairService = (RepairService) ORDER_SERVICE.get(orderType);
                repairService.update(factory, (RepairPo) order);
                return;
        }

    }



    //转派工单
    //@Override
    //@TaskAnnotation("reassign")
    //public OrderReassignPo reassign(SessionFactory factory, OrderReassignPo orderReassignPo) {
    //
    //    orderReassignPo.setOrderType(OrderType.DEFECT);
    //    orderReassignService.insertOrUpdate(factory, orderReassignPo);
    //
    //    //工单修改为待派工状态
    //    DefectDTO defectDTO = new DefectDTO();
    //    defectDTO.setId(orderReassignPo.getOrderId());
    //    defectDTO.setMajor(orderReassignPo.getMajor());
    //    defectDTO.setStatus(DefectStatus.WAIT_DISPATCH.getStatus());
    //
    //    defectService.update(factory, defectDTO);
    //
    //    // 修改创建人
    //    Map<String,Object> param = new HashMap<>();
    //    param.put("id",orderReassignPo.getOrderId());
    //    param.put("updateBy",orderReassignPo.getWorker());
    //    param.put("updateByName",orderReassignPo.getWorkerName());
    //    param.put("updateTime",new Date());
    //    defectService.updateInfo(factory,param);
    //
    //    return orderReassignPo;
    //}

    DispatchMapper getDispatchMapper(SessionFactory factory) {

        if (OrderType.CHANGE.equals(ThreadLocalOrderChange.get())) {
            return factory.getMapper(ChangeDispatchMapper.class);
        }

        return factory.getMapper(DispatchMapper.class);
    }

}
